import * as Cesium from 'cesium'
import type { useEarthGroup } from './EarthViewerGroup';
import { MaskPopup, RandomlyNum } from '@/utils/UtilFn';
import type { DrawDataType, UseMainResultType } from '@/type/UseDraw';
import { WeatherEnum } from '@/type/WeatherEnum.d';
import { CircleWave } from '../Material/CircleWaveMaterialProperty.js'
import { EllipsoidElectricMaterialProperty } from '../Material/ellipsoidElectricMaterialProperty.js'
import { RadarWaveMaterialProperty } from '../Material/RadarWaveMaterialProperty.js'
import { LineFlowMaterialProperty } from '../Material/lineFlowMaterialProperty.js'

import { parabola } from './earthFn';
import { useDrawWeather } from './DrawWeather';
import type { Entity } from 'cesium';

export class useDrawGraphical {
    // 图层组
    group: useEarthGroup;
    viewer: Cesium.Viewer;
    // 放置抛物线所有图形id的盒子
    ParabolaIds: string[] = new Array(0);
    // 绘制天气的对象
    DrawWeather: useDrawWeather;
    constructor(group: useEarthGroup, view: Cesium.Viewer) {
        if (!group || !view) {
            throw new Error("请将图层或组传入--DrawGraphical")
        }

        this.DrawWeather = new useDrawWeather(group, view);

        this.group = group;
        this.viewer = view;
    }
    useMain(type: string, item?: any): UseMainResultType | null {

        return this.ByTypeDrawLayer(type, item)
    }
    /**
     * 根据类型绘制不同的图形
     * @param type 需要绘制图形的类型
     * @returns 
     */
    private ByTypeDrawLayer(type: string, item?: DrawDataType): UseMainResultType | null {
        let obj = null;
        
        switch (type) {
            case "POINT":
                obj = this.drawPoint(item);
                break;
            case "LINE":
                obj = this.drawLine(item)
                break;
            case "POLYGON":
                obj = this.drawPolygon(item)
                break;
            case "PLANE":
                obj = this.drawPlane(item)
                break;
            case "CIRCLE":
                obj = this.drawCirCle(item)
                break;
            case "Label":
                obj = this.drawTextLabel(item)
                break;
            case "LabelAndPoint":
                obj = this.drawTextPoint(item)
                break;
            case "LINE_Super":
                obj = this.drawLineSuper(item)
                break;
            case "TERENTS_CIRCLE":
                obj = this.drawWaterCircle(item)
                break;
            case "PATH":
                obj = this.drawPath(item)
                break;
            case "LabelAndBill":
                obj = this.drawTextbill(item)
                break;
            case "ELLIPSE":
                obj = this.drawEllipseCircle(item)
                break;
            case "CYLINDER":
                obj = this.drawCylinder(item)
                break;
            case "RIPPLE_ELLIPSE":
                obj = this.drawRipple(item)
                break;
            case "INDUATION_POLYGON":
                obj = this.drawInduate(item)
                break;
            case "MODEL":
                obj = this.drawModel(item)
                break;
            case WeatherEnum.SNOW:
                obj = this.DrawWeather.drawSnow(type, item)
                break;
            case WeatherEnum.RAIN:
                obj = this.DrawWeather.drawRain(type, item)
                break;
            case WeatherEnum.FOG:
                obj = this.DrawWeather.drawFog(type, item)
                break;
            default:
                MaskPopup("此类型无法绘制")
                break;
        }
        return obj;
    }
    /**  
     * 为实体对象生成id
     * @returns string
     */
    private MakeEntityId() {
        let id = RandomlyNum();
        let flag = this.group.groupIsContains(id);
        if (flag) {
            id = id + RandomlyNum()
        }
        return id.toString();
    }
    /**
     * 去重操作
     * @param item 需要去重的元素
     */
    private DuplicateDraw(item?: DrawDataType | string) {

        if (typeof item == "string") {
            this.group.removeGroupEntityById(item)
        } else {
            item && this.group.removeGroupEntityById(item.id)

            // 如果当前需要去重的是抛物线
            item?.type == "LINE_Super" && this.ParabolaIds.forEach((item: any, index: number) => {
                this.group.removeGroupEntityById(item)
            })
            this.ParabolaIds = []
        }
    }
    /**
     * 绘制点
     * @returns 对象：实体/对象数据
     */
    drawPoint(item?: DrawDataType) {
        let self = this;
        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制点",
            position: [0, 0],
            type: "POINT",
            size: 10,
            color: "#090",
            outlineColor: "#0a1",
            outlineWidth: 2
        }

        let option = {
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1]),
            point: {
                pixelSize: Number(result.size),
                color: Cesium.Color.fromCssColorString(result.color),
                outlineColor: Cesium.Color.fromCssColorString(result.outlineColor),
                outlineWidth: Number(result.outlineWidth)
            }
        }
        let entity = this.group.addEntity(option);
        return { entity, result };
    }
    /**
     * 绘制线
     * @returns 对象：实体/对象数据
     */
    drawLine(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            type: "LINE",
            name: "绘制线",
            color: "#00c",
            width:2,
            position: []
        }

        this.DuplicateDraw(item);

        let option = {
            id: result.id,
            name: result.name,
            polyline: {
                ...result,
                positions: item ? result.position.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1])) : [],
                material: Cesium.Color.fromCssColorString(result.color),
                arcType: Cesium.ArcType.GEODESIC
            }
        }
        let entity = this.group.addEntity(option);
        return { entity, result };
    }
    /**
     * 绘制面
     */
    drawPolygon(item?: DrawDataType) {
        let self = this;
        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制面",
            color: "#00c",
            type: "POLYGON",
            position: [],
            height: 10,
            outlineColor: "#c00",
            outlineWidth: 3
        }
        let option = {
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(-107.00, 40.0, 3.0),
            polygon: {
                height: Number(result.height),
                hierarchy: {
                    positions: item ? result.position.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1])) : []
                },
                outline: true,
                material: Cesium.Color.fromCssColorString(result.color),
                outlineColor: Cesium.Color.fromCssColorString(result.outlineColor),
                outlineWidth: Number(result.outlineWidth),
                arcType: Cesium.ShadowMode.CAST_ONLY
            }
        }

        let entity = this.group.addEntity(option);
        return { entity, result };
    }
    /**
     * 绘制平面
     * @param item 
     * @returns 
     */
    drawPlane(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制平面",
            position: [0, 0],
            url: "",
            color: "#090",
            type: "PLANE",
            planeSize: [100, 100],
            outlineWidth: 10,
            outlineColor: "#0aa"
        }
        this.DuplicateDraw(item);
        let video = result.url ? this.createVideo(result.id, result.url) : false;
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1], (result.position[2] || 0)),
            plane: {
                material: video || Cesium.Color.fromCssColorString(result.color),
                plane: Cesium.Plane.ORIGIN_ZX_PLANE,
                dimensions: result.planeSize && Cesium.Cartesian2.fromElements(result.planeSize[0] * 100, result.planeSize[1] * 100),
                outlineColor: Cesium.Color.fromCssColorString(result.outlineColor),
                outlineWidth: Number(result.outlineWidth)
            }
        });
        return { entity, result }
    }
    /**
     * 绘制圆
     * @param item 
     * @returns 
     */
    drawCirCle(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制圆",
            position: [0, 0],
            type: "CIRCLE",
            semiMinorAxis: 1000.0,
            semiMajorAxis: 1000.0,
            color: "#090",
            url: '',
        }

        this.DuplicateDraw(item);
        let entity = self.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1]),
            ellipse: {
                semiMinorAxis: Number(result.semiMinorAxis),
                semiMajorAxis: Number(result.semiMajorAxis),
                material: result.url ? new Cesium.ImageMaterialProperty({
                    image: result.url
                }) : Cesium.Color.fromCssColorString(result.color)
            }
        })
        return { entity, result }
    }
    /**
     * 绘制文字标签
     * @param item 
     * @returns 
     */
    drawTextLabel(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制文字标签",
            position: [0, 0],
            type: "Label",
            text: "文字标签",
            color: "#090",
            pixelOffset: [0, 0],
            fontSize: 15
        }
        this.DuplicateDraw(item);
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1]),
            label: {
                text: result.text,
                fillColor: Cesium.Color.fromCssColorString(result.color),
                pixelOffset: result.pixelOffset && Cesium.Cartesian2.fromElements(result.pixelOffset[0], result.pixelOffset[1]),
                font: `${Number(result.fontSize)}px 微软雅黑`,
            }
        })
        return { entity, result }
    }
    /**
     * 绘制标签点
     * @param item 
     * @returns 
     */
    drawTextPoint(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制文字点",
            position: [0, 0],
            color: "#09a",
            type: "LabelAndPoint",
            text: "文字标签",
            size: 10,
            pixelOffset: [0, 0],
            fontSize: 15,
            outlineWidth: 2,
            outlineColor: "#090"
        }
        this.DuplicateDraw(item);
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1]),
            point: {
                show: true,
                pixelSize: Number(result.size),
                color: Cesium.Color.fromCssColorString(result.color),
                outlineWidth: Number(result.outlineWidth),
                outlineColor: Cesium.Color.fromCssColorString(result.outlineColor),
            },
            label: {
                text: result.text,
                fillColor: Cesium.Color.fromCssColorString(result.color),
                pixelOffset: result.pixelOffset && Cesium.Cartesian2.fromElements(result.pixelOffset[0], result.pixelOffset[1]),
                font: `${result.fontSize}px 微软雅黑`,
            }
        })
        return { entity, result }
    }
    /**
     * 绘制抛物线
     * @param item 
     * @returns 
     */
    drawLineSuper(item?: DrawDataType) {
        let self = this;
        this.DuplicateDraw(item);
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制抛物线",
            position: [],
            color: "#09a",
            type: "LINE_Super",
            height: 1000,
            size: 10,
            speed: 2,
            outlineWidth: 2,
            outlineColor: "#090"
        }

        let _positions = result.position;
        let _center = _positions.length > 0 && _positions[0];
        let entity = null;
        _positions.forEach((item: any, index: number) => {

            if (index == 0) return;
            let _siglePositions = parabola(_center, item, result.height ? result.height * 100 : 10000);
            // 创建飞线
            for (let i = 0; i < 3; i++) {
                let id = result.id + index + i;
                self.ParabolaIds.push(id);
                self.DuplicateDraw(id)
                self.group.addEntity({
                    id: id,
                    name: result.name + "辅助标签",
                    polyline: {
                        positions: _siglePositions,
                        material: new LineFlowMaterialProperty({
                            color: Cesium.Color.fromCssColorString(result.color),
                            speed: result.speed * Math.random(),
                            percent: 0.1,
                            gradient: 0.01,
                        }),
                    },
                });
            }
            let id = result.id + index + "line";
            self.ParabolaIds.push(id);
            self.DuplicateDraw(id)
            // 创建轨迹线
            entity = self.group.addEntity({
                id: id,
                name: result.name,
                positions: _siglePositions[0],
                polyline: {
                    width: result.outlineWidth,
                    positions: _siglePositions,
                    material: Cesium.Color.fromCssColorString(result.outlineColor),
                }
            });
        })
        if (entity == null) {
            let option = {
                id: result.id,
                name: result.name,
                show: false,
                position: Cesium.Cartesian3.fromDegrees(0, 0),
                point: {
                    pixelSize: Number(result.size),
                    color: Cesium.Color.fromCssColorString(result.color),
                }
            }
            entity = self.group.addEntity(option)
        }

        return { entity, result }
    }
    /**
     * 绘制标签图标
     * @param item 
     * @returns 
     */
    drawTextbill(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            name: "绘制标签图标",
            position: [0, 0],
            color: "#09a",
            type: "LabelAndBill",
            text: "文字标签",
            url: '',
            size: 10,
            scale: 1,
            width: 100,
            height: 100,
            pixelOffset: [0, 0],
            fontSize: 15,
        }
        this.DuplicateDraw(item);

        let u = "";
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1]),
            billboard: {
                image: result.url || u,
                scale: Number(result.scale),
                width: Number(result.width),
                height: Number(result.height),
                clampToGroud: true
            },
            label: {
                text: result.text,
                fillColor: Cesium.Color.fromCssColorString(result.color),
                pixelOffset: result.pixelOffset && Cesium.Cartesian2.fromElements(result.pixelOffset[0], result.pixelOffset[1]),
                font: `${result.fontSize}px 微软雅黑`,
            }
        })
        return { entity, result }
    }
    /**
     * 绘制带有扩散效果的圆
     * @param item 
     * @returns 
     */
    drawWaterCircle(item?: DrawDataType) {
        let self = this;
        let result = item || {
            id: self.MakeEntityId(),
            position: [0, 0],
            color: "#09a",
            radius: 5000,
            type: "TERENTS_CIRCLE",
            duration: 3000
        }
        this.DuplicateDraw(item);
        let circleWave = new CircleWave(this.viewer, result.id);
        let entity = circleWave.add([result.position[0], result.position[1], 0], result.color, result.radius, result.duration);
        // 组内添加元素
        this.group.addEntity(entity);

        return { entity, result }
    }
    /**
     * 绘制路径图
     * @param item 
     * @returns 
     */
    drawPath(item?: DrawDataType) {
        if (item) {
            return this.path_run(item)
        } else {
            return this.addPathLine()
        }
    }
    // 新增路径，添加路径线
    addPathLine() {
        let id = this.MakeEntityId();

        let result = {
            id,
            name: "绘制路径线",
            color: "red",
            position: [],
            width: 3,
            type: "PATH",
            height: 5,
            url: '',
            size: 10,
            extrudedHeight: 30,
            istracked: false
        }

        let option = {
            id: id,
            name: result.name,
            polyline: {
                width: Number(result.width),
                height: Number(result.height),
                fill: true,
                extrudedHeight: Number(result.extrudedHeight),
                material: Cesium.Color.fromCssColorString(result.color),
                arcType: Cesium.ArcType.GEODESIC
            }
        }
        let entity = this.group.addEntity(option);
        return { entity, result };
    }
    // 已有路径数据，根据数据绘制动态路径效果
    path_run(item: any) {
        this.DuplicateDraw(item);
        let dataSource = item.position;
        let property = new Cesium.SampledPositionProperty();
        let startTime = new Date();
        let time = startTime.getTime();
        let stopTime: Date = new Date();
        dataSource.forEach((item: any, index: number) => {
            let date = new Date(time + index * (item.interval || 5000));
            stopTime = date;
            property.addSample(Cesium.JulianDate.fromDate(date), Cesium.Cartesian3.fromDegrees(item[0], item[1], item[2] || 0));
        })
        property.setInterpolationOptions({
            interpolationDegree: 0.0001,
            interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
        })

        let entityid = item.id + "1"
        let entid = item.id + "2"
        this.group.removeGroupEntityById(entityid)
        this.group.removeGroupEntityById(entid)

        // 创建路线图
        let entity = this.group.addEntity({
            id: entityid,
            name: item.name,
            position: Cesium.Cartesian3.fromDegrees(dataSource[0][0], dataSource[0][1], (dataSource[0][2] || 0)),
            polyline: {
                positions: dataSource.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1], (t[2] || 0))),
                width: Number(item.width),
                height: Number(item.height),
                fill: true,
                extrudedHeight: Number(item.extrudedHeight),
                material: Cesium.Color.fromCssColorString(item.color).withAlpha(0.4),
                arcType: Cesium.ArcType.GEODESIC
            }
        })

        let ent = this.group.addEntity({
            id: entid,
            name: "回放线",
            availability: new Cesium.TimeIntervalCollection([
                new Cesium.TimeInterval({
                    start: Cesium.JulianDate.fromDate(startTime),
                    stop: Cesium.JulianDate.fromDate(stopTime)
                })
            ]),
            position: property,
            model: {
                show: true,
                uri: item.url || '',
                clampAnimations: true,
                minimumPixelSize: item.size,
                maximumScale: 70
            },
            path: {
                leadTime: 0,
                trailTime: 1,
                material: Cesium.Color.fromCssColorString(item.color),
                width: Number(item.width)
            },
        })

        // 是否开启跟随模式
        item.istracked && (this.viewer.trackedEntity = (ent as Entity));
        this.viewer.clock.currentTime = Cesium.JulianDate.fromDate(startTime)
        this.viewer.clock.stopTime = Cesium.JulianDate.fromDate(stopTime)
        this.viewer.clock.clockRange = Cesium.ClockRange.CLAMPED;
        this.viewer.clock.shouldAnimate = true;

        return { entity, result: item }
    }
    /**
     * 绘制电弧圆
     * @param item 
     * @returns 
     */
    drawEllipseCircle(item?: DrawDataType) {
        let self = this;
        this.DuplicateDraw(item);
        let result = item || {
            id: self.MakeEntityId(),
            position: [0, 0],
            color: "#09a",
            radius: 5000,
            type: "ELLIPSE",
            speed: 10
        }
        let entity = self.group.addEntity({
            id: result.id,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1], (result.position[2] || 0)),
            name: '电弧球体',
            ellipsoid: {
                radii: new Cesium.Cartesian3(result.radius, result.radius, result.radius),
                material: new EllipsoidElectricMaterialProperty({
                    color: Cesium.Color.fromCssColorString(result.color),
                    speed: Number(result.speed)
                })
            }
        })
        return { entity, result }
    }
    /**
     * 绘制圆柱体
     * @param item 
     * @returns 
     */
    drawCylinder(item?: DrawDataType) {
        let self = this;

        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "圆柱",
            position: [0, 0],
            color: "#09a",
            size: 5000,
            topRadius: 500,
            url: '',
            bottomRadius: 500,
            type: "CYLINDER",
        }
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1], (result.position[2] || 0)),
            cylinder: {
                length: Number(result.size),
                topRadius: Number(result.topRadius),
                bottomRadius: Number(result.bottomRadius),
                fill: true,
                material: this.getCylinderMaterial(result)
            }
        })
        return { entity, result }
    }
    getCylinderMaterial(item: any) {
        if (item.url) {
            return new Cesium.ImageMaterialProperty({
                image: item.url,
                repeat: new Cesium.Cartesian2(1, 1)
            })
        } else {
            return Cesium.Color.fromCssColorString(item.color)
        }
    }
    /**
     * 绘制波纹雷达
     * @param item 
     */
    drawRipple(item?: DrawDataType) {
        let self = this;

        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "波纹雷达",
            position: [0, 0],
            color: "#09a",
            size: 5000,
            semiMajorAxis: 1000.0,
            semiMinorAxis: 1000.0,
            speed: 20.0,
            type: "RIPPLE_ELLIPSE",
        }

        let entity = this.group.addEntity({
            id: result.id,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1], (result.position[2] || 0)),
            name: result.name,
            ellipse: {
                semiMajorAxis: Number(result.semiMajorAxis) * 100,
                semiMinorAxis: Number(result.semiMinorAxis) * 100,
                material: new RadarWaveMaterialProperty({
                    color: Cesium.Color.fromCssColorString(result.color),
                    speed: Number(result.speed)
                })
            }
        })
        return { entity, result }
    }
    /**
     * 绘制淹没效果
     * @param item 
     */
    drawInduate(item?: DrawDataType) {
        let self = this;

        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "淹没效果",
            position: [],
            color: "rgba(209, 187, 22, 1)",
            type: "INDUATION_POLYGON",
            speed: 0.2,
            extrudedHeight: 300
        }


        let waterHeight: any = 0;
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            polygon: {
                hierarchy: {
                    positions: item ? result.position.map((t: any) => Cesium.Cartesian3.fromDegrees(t[0], t[1])) : []
                },
                perPositionHeight: true,
                // 使用回调函数Callback，直接设置extrudedHeight会导致闪烁
                extrudedHeight: new Cesium.CallbackProperty(function () {
                    if (!item) {
                        return result.extrudedHeight;
                    }
                    waterHeight += 0.2;
                    if (waterHeight > (result.extrudedHeight || 300)) {
                        waterHeight = result.extrudedHeight;
                    }
                    return waterHeight;
                }, false),
                material: Cesium.Color.fromCssColorString(result.color)
            }
        })
        return { entity, result }
    }
    drawModel(item?: DrawDataType) {
        let self = this;

        this.DuplicateDraw(item);

        let result = item || {
            id: self.MakeEntityId(),
            name: "模型",
            position: [0, 0],
            color: "#09a",
            size: 5000,
            url: '',
            type: "MODEL",
            scale: 1,
        }
        let entity = this.group.addEntity({
            id: result.id,
            name: result.name,
            position: Cesium.Cartesian3.fromDegrees(result.position[0], result.position[1], (result.position[2] || 0)),
            model: {
                uri: result.url || '',
                scale: result.scale,
                minimumPixelSize: result.size,
                color: Cesium.Color.fromCssColorString(result.color).withAlpha(0.8)
            }
        })
        return { entity, result }
    }
    // 创建视频元素
    createVideo(id: string, url: string | HTMLCanvasElement) {
        if (!url || url instanceof HTMLCanvasElement) return false;
        var videoElement = document.createElement('video');
        videoElement.src = url; // 替换为你的视频文件路径
        videoElement.loop = true; // 让视频循环播放
        videoElement.muted = true; // 设置视频静音（如果需要）
        videoElement.controls = true;
        videoElement.play(); // 播放视频

        videoElement.classList.add(id);
        videoElement.classList.add("PlaneVideo");

        document.body.appendChild(videoElement);

        return videoElement;
    }

}